#!/usr/bin/env node

/**
 * 主运行文件
 * 
 * 用法：
 *   node run.js                     # 执行所有任务（使用默认模式）
 *   node run.js --parallel          # 并发执行所有任务
 *   node run.js --sequential        # 顺序执行所有任务
 *   node run.js --concurrent        # 限制并发执行所有任务
 *   node run.js --task taobao       # 只执行指定任务
 *   node run.js --task taobao,jd    # 执行多个指定任务
 *   node run.js --list              # 列出所有可用任务
 */

const fs = require('fs');
const path = require('path');
const TaskManager = require('./task-manager');
const config = require('./tasks.config');
const dbConnection = require('./db/connection');
const CrawlResult = require('./db/models/CrawlResult');

// ==================== 工具函数 ====================

/**
 * 加载任务配置
 * @param {string} taskName - 任务名称
 * @param {boolean} ignoreEnabled - 是否忽略 enabled 检查（用于单独测试）
 * @returns {Object|null} 任务配置对象
 */
function loadTask(taskName, ignoreEnabled = false) {
    try {
        const taskPath = path.join(__dirname, 'tasks', taskName, 'index.js');
        if (!fs.existsSync(taskPath)) {
            console.warn(`⚠️  警告: 任务 "${taskName}" 不存在，跳过`);
            return null;
        }
        
        const taskConfig = require(taskPath);
        
        // 检查任务是否启用（除非明确忽略检查）
        if (!ignoreEnabled && taskConfig.enabled === false) {
            console.log(`⏭️  跳过已禁用的任务: ${taskName}`);
            return null;
        }
        
        // 如果是单独测试禁用的任务，给出提示
        if (ignoreEnabled && taskConfig.enabled === false) {
            console.log(`🔧 正在测试已禁用的任务: ${taskName} (仅用于调试)`);
        }
        
        return taskConfig;
    } catch (error) {
        console.error(`❌ 加载任务 "${taskName}" 失败:`, error.message);
        return null;
    }
}

/**
 * 加载所有任务
 * @param {Array<string>} taskNames - 任务名称数组
 * @param {boolean} ignoreEnabled - 是否忽略 enabled 检查
 * @returns {Array<Object>} 任务配置数组
 */
function loadTasks(taskNames, ignoreEnabled = false) {
    const tasks = [];
    
    for (const taskName of taskNames) {
        const task = loadTask(taskName, ignoreEnabled);
        if (task) {
            tasks.push(task);
        }
    }
    
    return tasks;
}

/**
 * 列出所有可用任务
 */
function listTasks() {
    console.log('\n' + '='.repeat(60));
    console.log('📋 可用任务列表');
    console.log('='.repeat(60));
    
    const tasksDir = path.join(__dirname, 'tasks');
    const folders = fs.readdirSync(tasksDir, { withFileTypes: true })
        .filter(dirent => dirent.isDirectory())
        .map(dirent => dirent.name)
        .filter(name => !name.startsWith('_')); // 排除模板文件夹
    
    if (folders.length === 0) {
        console.log('没有找到任务');
        return;
    }
    
    folders.forEach((folder, index) => {
        const taskPath = path.join(tasksDir, folder, 'index.js');
        if (fs.existsSync(taskPath)) {
            try {
                const task = require(taskPath);
                const status = task.enabled === false ? '❌ 已禁用' : '✅ 已启用';
                const inConfig = config.tasks.includes(folder) ? '📌 已配置' : '  未配置';
                console.log(`${index + 1}. ${folder.padEnd(15)} ${status}  ${inConfig}  ${task.name || ''}`);
            } catch (error) {
                console.log(`${index + 1}. ${folder.padEnd(15)} ⚠️  加载失败`);
            }
        }
    });
    
    console.log('\n' + '='.repeat(60));
    console.log(`总计: ${folders.length} 个任务`);
    console.log('='.repeat(60) + '\n');
}

/**
 * 保存结果到文件
 * @param {Array} results - 执行结果
 */
function saveResults(results) {
    if (!config.output.saveToFile) {
        return;
    }
    
    try {
        // 创建输出目录
        const outputDir = path.join(__dirname, config.output.outputDir);
        if (!fs.existsSync(outputDir)) {
            fs.mkdirSync(outputDir, { recursive: true });
        }
        
        // 生成文件名
        const now = new Date();
        const date = now.toISOString().split('T')[0];
        const time = now.toTimeString().split(' ')[0].replace(/:/g, '-');
        const timestamp = now.getTime();
        
        let fileName = config.output.fileNameFormat
            .replace('{date}', date)
            .replace('{time}', time)
            .replace('{timestamp}', timestamp);
        
        const filePath = path.join(outputDir, fileName);
        
        // 保存结果
        fs.writeFileSync(filePath, JSON.stringify(results, null, 2), 'utf-8');
        console.log(`\n💾 结果已保存到: ${filePath}`);
        
    } catch (error) {
        console.error('❌ 保存结果失败:', error.message);
    }
}

/**
 * 保存结果到数据库
 * @param {Array} results - 执行结果
 * @param {string} executionMode - 执行模式
 * @param {string} batchId - 批次 ID
 */
async function saveToDatabase(results, executionMode, batchId) {
    if (!config.database || !config.database.enabled) {
        return;
    }
    
    try {
        console.log('\n📊 正在保存结果到数据库...');
        
        // 准备要保存的文档
        const documents = results.map(result => ({
            taskName: result.taskName || '未知任务',
            success: result.success || false,
            url: result.url,
            title: result.title,
            data: result.data,
            error: result.error,
            crawlTimestamp: result.timestamp ? new Date(result.timestamp) : new Date(),
            batchId: batchId,
            executionMode: executionMode,
            metadata: {
                savedAt: new Date(),
                environment: process.env.NODE_ENV || 'development'
            }
        }));
        
        // 批量插入数据
        const savedResults = await CrawlResult.insertMany(documents);
        console.log(`✅ 成功保存 ${savedResults.length} 条记录到数据库`);
        
        // 打印统计信息
        const successCount = savedResults.filter(r => r.success).length;
        const failureCount = savedResults.length - successCount;
        console.log(`   成功: ${successCount} 条，失败: ${failureCount} 条`);
        
    } catch (error) {
        const errorMsg = `❌ 保存到数据库失败: ${error.message}`;
        console.error(errorMsg);
        
        if (!config.database.continueOnError) {
            throw error;
        }
    }
}

/**
 * 打印结果摘要
 * @param {Array} results - 执行结果
 */
function printResults(results) {
    if (!config.output.verbose) {
        return;
    }
    
    console.log('\n' + '='.repeat(60));
    console.log('📊 执行结果详情');
    console.log('='.repeat(60));
    
    results.forEach((result, index) => {
        console.log(`\n${index + 1}. ${result.taskName || '未知任务'}`);
        console.log(`   状态: ${result.success ? '✅ 成功' : '❌ 失败'}`);
        console.log(`   URL: ${result.url || 'N/A'}`);
        
        if (result.success) {
            console.log(`   标题: ${result.title || 'N/A'}`);
            if (result.data) {
                console.log(`   数据: ${JSON.stringify(result.data).substring(0, 100)}...`);
            }
        } else {
            console.log(`   错误: ${result.error || 'N/A'}`);
        }
    });
    
    console.log('\n' + '='.repeat(60));
}

// ==================== 命令行参数解析 ====================

function parseArgs() {
    const args = process.argv.slice(2);
    const options = {
        mode: config.defaultMode,
        tasks: null,
        list: false,
    };
    
    for (let i = 0; i < args.length; i++) {
        const arg = args[i];
        
        if (arg === '--parallel' || arg === '-p') {
            options.mode = 'parallel';
        } else if (arg === '--sequential' || arg === '-s') {
            options.mode = 'sequential';
        } else if (arg === '--concurrent' || arg === '-c') {
            options.mode = 'concurrent';
        } else if (arg === '--task' || arg === '-t') {
            if (i + 1 < args.length) {
                options.tasks = args[i + 1].split(',').map(t => t.trim());
                i++;
            }
        } else if (arg === '--list' || arg === '-l') {
            options.list = true;
        } else if (arg === '--help' || arg === '-h') {
            console.log(`
使用方法：
  node run.js [选项]

选项：
  -p, --parallel      并发执行所有任务（默认）
  -s, --sequential    顺序执行所有任务
  -c, --concurrent    限制并发执行所有任务
  -t, --task <名称>   只执行指定任务（多个任务用逗号分隔）
                      💡 使用 --task 时会忽略 enabled 状态，方便调试
  -l, --list          列出所有可用任务
  -h, --help          显示帮助信息

示例：
  node run.js                     # 执行所有任务（并发）
  node run.js --sequential        # 顺序执行所有任务
  node run.js --task taobao       # 只执行淘宝任务
  node run.js --task taobao,jd    # 执行淘宝和京东任务
  node run.js --task disabled     # 即使任务被禁用也可以测试
  node run.js --list              # 列出所有任务

注意：
  - 使用 --task 指定任务时，会自动忽略任务的 enabled 状态
  - 这样即使任务设置了 enabled: false，也可以单独测试调试
            `);
            process.exit(0);
        }
    }
    
    return options;
}

// ==================== 主函数 ====================

async function main() {
    console.log('========================================');
    console.log('    多网站爬虫任务执行器');
    console.log('========================================\n');
    
    // 解析命令行参数
    const options = parseArgs();
    
    // 列出任务
    if (options.list) {
        listTasks();
        return;
    }
    
    // 确定要执行的任务
    const taskNames = options.tasks || config.tasks;
    
    if (!taskNames || taskNames.length === 0) {
        console.error('❌ 没有要执行的任务');
        console.log('💡 使用 --list 查看可用任务');
        return;
    }
    
    // 加载任务配置
    // 如果使用 --task 明确指定任务，则忽略 enabled 检查（方便调试）
    const ignoreEnabled = !!options.tasks;
    console.log('📥 正在加载任务配置...\n');
    const tasks = loadTasks(taskNames, ignoreEnabled);
    
    if (tasks.length === 0) {
        console.error('❌ 没有有效的任务可执行');
        return;
    }
    
    console.log(`✅ 已加载 ${tasks.length} 个任务\n`);
    
    // 连接数据库（如果启用）
    if (config.database && config.database.enabled) {
        try {
            await dbConnection.connect();
        } catch (error) {
            console.error('⚠️  数据库连接失败，将只保存到文件');
            if (!config.database.continueOnError) {
                return;
            }
        }
    }
    
    // 创建任务管理器
    const manager = new TaskManager({
        headless: config.browser.headless,
        slowMo: config.browser.slowMo,
        stealth: config.browser.stealth,
        maxConcurrent: config.maxConcurrent,
        delayBetweenTasks: config.delayBetweenTasks,
        delayBetweenBatches: config.delayBetweenBatches,
    });
    
    // 生成批次 ID
    const batchId = `batch_${Date.now()}`;
    
    try {
        // 添加任务
        manager.addTasks(tasks);
        
        // 根据模式执行任务
        let results;
        switch (options.mode) {
            case 'parallel':
                results = await manager.runParallel();
                break;
            case 'sequential':
                results = await manager.runSequential();
                break;
            case 'concurrent':
                results = await manager.runConcurrent();
                break;
            default:
                console.error(`❌ 未知的执行模式: ${options.mode}`);
                return;
        }
        
        // 打印结果
        printResults(results);
        
        // 保存结果到文件
        saveResults(results);
        
        // 保存结果到数据库
        if (config.database && config.database.enabled) {
            await saveToDatabase(results, options.mode, batchId);
        }
        
    } catch (error) {
        console.error('❌ 执行过程中出错:', error);
    } finally {
        // 关闭浏览器
        await manager.close();
        
        // 关闭数据库连接
        if (config.database && config.database.enabled) {
            await dbConnection.disconnect();
        }
    }
}

// ==================== 运行 ====================

if (require.main === module) {
    main().catch(console.error);
}

module.exports = main;

